package com.kpi.processflow.record;

import com.google.common.base.Joiner;
import com.google.common.collect.Lists;
import lombok.Data;

import java.util.*;
import java.util.concurrent.TimeUnit;

/**
 * @author Kevin Liu
 * @date 2020/5/3 6:54 下午
 */
@Data
public class StageStack {
    private List<Stage> stages = Lists.newArrayList();

    StageStack() {
    }

    public void push(Stage stage) {
        this.stages.add(stage);
    }

    private Stage peekUnreleasedStage() {
        if (null != this.stages && !this.stages.isEmpty()) {
            ListIterator iterator = this.stages.listIterator(this.stages.size());

            Stage stage;
            do {
                if (!iterator.hasPrevious()) {
                    return null;
                }

                stage = (Stage)iterator.previous();
            } while(stage.isReleased());

            return stage;
        } else {
            return null;
        }
    }

    public void release() {
        Stage stage = this.peekUnreleasedStage();
        if (null != stage) {
            stage.release();
        }
    }

    public void releaseAll() {
        if (null != this.stages && !this.stages.isEmpty()) {
            ListIterator iterator = this.stages.listIterator(this.stages.size());
            while(iterator.hasPrevious()) {
                Stage stage = (Stage)iterator.previous();
                if (!stage.isReleased()) {
                    stage.release();
                }
            }

        }
    }

    public String dump(boolean allDump) {
        if (null != this.stages && !this.stages.isEmpty()) {
            Map<String, String> stageMap = new LinkedHashMap<>(this.stages.size());
            int counter = 0;
            for(int size = this.stages.size(); counter < size; ++counter) {
                Stage stage = (Stage)this.stages.get(counter);
                if (allDump || stage.isReleased()) {
                    String stageKey = counter + "-" + stage.getIdentifier();
                    String stageValue = stage.isReleased() ? String.valueOf(stage.getStopwatch().elapsed(TimeUnit.MILLISECONDS)) : "unreleased";
                    stageMap.put(stageKey, stageValue);
                }
            }

            return "{" + Joiner.on("|").withKeyValueSeparator(":").join(stageMap) + "}";
        } else {
            return "{UNRECORDED}";
        }
    }

}

